package cn.xingzhe.monster.user.application.service.impl;

import cn.xingzhe.monster.user.application.converter.RoleConverter;
import cn.xingzhe.monster.user.application.dto.RoleDTO;
import cn.xingzhe.monster.user.application.service.RoleApplicationService;
import cn.xingzhe.monster.user.domain.model.RoleModel;
import cn.xingzhe.monster.user.domain.model.UserModel;
import cn.xingzhe.monster.user.domain.repository.RoleRepository;
import cn.xingzhe.monster.user.domain.repository.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色应用服务实现
 *
 * @author System
 * @version 1.0.0
 * @since 2024-01-01
 */
@Service
public class RoleApplicationServiceImpl implements RoleApplicationService {

    private final RoleRepository roleRepository;
    private final RoleConverter roleConverter;
    private final UserRepository userRepository;

    public RoleApplicationServiceImpl(RoleRepository roleRepository,
                                     RoleConverter roleConverter,
                                     UserRepository userRepository) {
        this.roleRepository = roleRepository;
        this.roleConverter = roleConverter;
        this.userRepository = userRepository;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RoleDTO createRole(RoleDTO roleDTO) {
        // 使用领域模型创建角色
        RoleModel roleModel = RoleModel.create(
                roleDTO.getRoleCode(),
                roleDTO.getRoleName(),
                roleDTO.getDescription()
        );
        roleModel = roleRepository.save(roleModel);
        return roleConverter.toDTO(roleModel);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RoleDTO updateRole(String roleId, RoleDTO roleDTO) {
        RoleModel roleModel = roleRepository.findById(roleId)
                .orElseThrow(() -> new RuntimeException("角色不存在: " + roleId));
        
        // 使用领域模型方法更新信息
        roleModel = roleModel.updateInfo(roleDTO.getRoleName(), roleDTO.getDescription());
        
        if (roleDTO.getPermissionIds() != null) {
            roleModel = roleModel.assignPermissions(roleDTO.getPermissionIds());
        }
        
        roleModel = roleRepository.save(roleModel);
        return roleConverter.toDTO(roleModel);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRole(String roleId) {
        roleRepository.deleteById(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RoleDTO assignPermissionsToRole(String roleId, List<String> permissionIds) {
        RoleModel roleModel = roleRepository.findById(roleId)
                .orElseThrow(() -> new RuntimeException("角色不存在: " + roleId));
        
        // 使用领域模型方法分配权限
        roleModel = roleModel.assignPermissions(permissionIds);
        roleModel = roleRepository.save(roleModel);
        return roleConverter.toDTO(roleModel);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignRolesToUser(String userId, List<String> roleIds) {
        UserModel userModel = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在: " + userId));
        
        // 使用领域模型方法分配角色
        userModel = userModel.assignRoles(roleIds);
        userRepository.save(userModel);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeRolesFromUser(String userId, List<String> roleIds) {
        UserModel userModel = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在: " + userId));
        
        // 使用领域模型方法移除角色
        userModel = userModel.removeRoles(roleIds);
        userRepository.save(userModel);
    }

    @Override
    public RoleDTO getRoleById(String roleId) {
        RoleModel roleModel = roleRepository.findById(roleId)
                .orElseThrow(() -> new RuntimeException("角色不存在: " + roleId));
        return roleConverter.toDTO(roleModel);
    }

    @Override
    public List<RoleDTO> getAllRoles() {
        List<RoleModel> roles = roleRepository.findAll();
        return roles.stream()
                .map(roleConverter::toDTO)
                .collect(Collectors.toList());
    }
}

